package org.arch_learn.servlet_container.components;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpRequestDecoder;
import io.netty.handler.codec.http.HttpResponseEncoder;
import io.netty.handler.stream.ChunkedWriteHandler;
import org.arch_learn.servlet_container.components.connector.Endpoint;
import org.arch_learn.servlet_container.components.container.Engine;

public class Service extends Thread {
    private String serviceName;
    private Engine engine;
    private Integer port;

    public Service withName(String name) {
        this.serviceName = name;
        return this;
    }

    public Service withPort(String port) {
        this.port = Integer.valueOf(port);
        return this;
    }

    public Service withEngine(Engine engine) {
        this.engine = engine;
        return this;
    }

    public Engine getEngine() {
        return engine;
    }

    public Integer getPort() {
        return port;
    }

    @Override
    public void run() {
        System.out.println("服务:" + serviceName + "正在处理请求---------");

        EventLoopGroup bossGroup = null;
        EventLoopGroup workerGroup = null;
        try {
            //1.创建bossGroup线程组，处理网络连接事件(主线程组设置2个线程,不设置的话默认为处理器线程数）
            bossGroup = new NioEventLoopGroup(1);
            //2.创建workGroup线程组，处理网络读写事件(从线程组设置10个线程,不设置的话默认为处理器线程数 * 2）
            workerGroup = new NioEventLoopGroup();
            //3.创建服务端启动助手
            ServerBootstrap serverBootstrap = new ServerBootstrap();
            //4.设置bossGroup线程组和workGroup线程组
            serverBootstrap.group(bossGroup, workerGroup)
                    //5.设置服务端通道（serverSocketChannel)为NIO
                    .channel(NioServerSocketChannel.class)
                    //6.bossGroup参数设置(设置连接等待个数)
                    .option(ChannelOption.SO_BACKLOG, 128)
                    //7.workGroup参数设置(设置活跃状态)
                    .childOption(ChannelOption.SO_KEEPALIVE, Boolean.TRUE)
                    //8.创建一个通道初始化对象
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel channel) throws Exception {
                            //9.向pipeline中添加自定义业务处理handler
                            ChannelPipeline pipeline = channel.pipeline();
                            //添加Http编解码器
                            pipeline
//                                    .addLast("httpCodec", new HttpServerCodec())
                                    .addLast("http-decoder", new HttpRequestDecoder())
                                    .addLast("http-aggregator", new HttpObjectAggregator(65536))

                                    .addLast("http-encoder", new HttpResponseEncoder())
                                    .addLast("http-chunked", new ChunkedWriteHandler())
                                    //自定义业务处理类
                                    .addLast(new Endpoint(Service.this));
                        }
                    });
            //10.启动服务端并绑定端口，同时将异步改成同步
            ChannelFuture channelFuture = serverBootstrap.bind(port);
//                .sync();
            channelFuture.addListener((ChannelFutureListener) channelFuture1 -> {
                if (channelFuture1.isSuccess()) {
                    System.out.println("端口绑定成功！");
                } else {
                    System.out.println("端口绑定失败！");
                }
            });
            System.out.println("Netty Http服务端启动成功！");
            //11.关闭通道(并不是真正意义上的关闭，而是监听通道关闭的状态)和关闭连接池
            channelFuture.channel().closeFuture().sync();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //有通道关闭，才会执行下面代码，因为上一行代码的sync方法使线程阻塞在上一行了。
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }
}
